package sunyu.controller;

import org.quartz.*;
import org.quartz.impl.StdScheduler;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import sunyu.toolkit.core.LogKit;

import javax.annotation.Resource;
import java.util.*;

/**
 * 定时任务控制器
 *
 * @author 孙宇
 */
@Controller
@RequestMapping("/quartz/job")
public class QuartzJobController extends CommonController {

    private static final Logger logger = LogKit.getLogger();

    @Resource(name = "schedulerFactoryBean")
    private StdScheduler scheduler;

    /**
     * 显示任务列表
     *
     * @param model
     * @return
     * @throws SchedulerException
     */
    @RequestMapping(value = "list", method = RequestMethod.GET)
    public String list(Model model) throws SchedulerException {
        String schedulerName = scheduler.getSchedulerName();
        List<Map<String, Object>> jobs = new ArrayList<>();
        for (String jobGroupName : scheduler.getJobGroupNames()) {
            for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(jobGroupName))) {
                String jobName = jobKey.getName();
                String jobGroup = jobKey.getGroup();
                List<Trigger> triggers = (List<Trigger>) scheduler.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers) {
                    TriggerKey triggerKey = trigger.getKey();
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);
                    String triggerStateName = null;
                    switch (triggerState.name()) {
                        case "PAUSED":
                            triggerStateName = "任务暂停";
                            break;
                        case "NORMAL":
                            triggerStateName = "等待执行";
                            break;
                        case "BLOCKED":
                            triggerStateName = "正在执行";
                            break;
                        default:
                            triggerStateName = triggerState.name();
                            break;
                    }
                    Map<String, Object> job = new HashMap<>();
                    job.put("triggerName", triggerKey.getName());
                    job.put("triggerGroup", triggerKey.getGroup());
                    job.put("jobGroup", jobGroup);
                    job.put("jobName", jobName);
                    job.put("startTime", trigger.getStartTime());
                    job.put("nextFireTime", trigger.getNextFireTime());
                    job.put("previousFireTime", trigger.getPreviousFireTime());
                    job.put("triggerState", triggerStateName);
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        job.put("cronExpression", cronExpression);
                    }
                    job.put("schedulerName", schedulerName);
                    jobs.add(job);
                }
            }
        }
        Collections.sort(jobs, (o1, o2) -> {
            if (o1.get("nextFireTime") != null && o2.get("nextFireTime") != null) {
                if (o1.get("nextFireTime") instanceof Date && o2.get("nextFireTime") instanceof Date) {
                    Date d1 = (Date) o1.get("nextFireTime");
                    Date d2 = (Date) o2.get("nextFireTime");
                    return d1.compareTo(d2);
                }
            }
            return String.valueOf(o1.get("nextFireTime")).compareTo(String.valueOf(o2.get("nextFireTime")));
        });
        model.addAttribute("jobs", jobs);
        return "/template/quartz/job/list";
    }

    /**
     * 更新任务启动时间
     *
     * @param triggerGroup
     * @param triggerName
     * @param cronExpression
     * @return
     */
    @RequestMapping("/updateCronExpression")
    public String updateCronExpression(@RequestParam(value = "triggerGroup", required = false) String triggerGroup,
                                       @RequestParam(value = "triggerName", required = false) String triggerName,
                                       @RequestParam(value = "cronExpression", required = false) String cronExpression) throws SchedulerException {
        if (CronExpression.isValidExpression(cronExpression)) {
            TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroup);
            if (triggerKey != null) {
                Trigger trigger = scheduler.getTrigger(triggerKey);
                if (trigger != null) {
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String oldCronExpression = cronTrigger.getCronExpression();
                        if (!oldCronExpression.equalsIgnoreCase(cronExpression)) {
                            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
                            triggerBuilder.withIdentity(triggerName, triggerGroup);
                            triggerBuilder.startNow();
                            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression));
                            scheduler.rescheduleJob(triggerKey, triggerBuilder.build());
                        }
                    }
                }
            }
        }
        return "redirect:/quartz/job/list";
    }

    /**
     * 操作任务
     *
     * @param jobGroup
     * @param jobName
     * @return
     */
    @RequestMapping("/{action}")
    public String execute(@PathVariable(value = "action") String action,
                          @RequestParam(value = "jobGroup", required = false) String jobGroup,
                          @RequestParam(value = "jobName", required = false) String jobName) throws SchedulerException {
        if (action.equals("pauseAll")) {
            scheduler.pauseAll();
        } else if (action.equals("resumeAll")) {
            scheduler.resumeAll();
        } else {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
            switch (action) {
                case "delete":
                    scheduler.deleteJob(jobKey);
                    break;
                case "resume":
                    scheduler.resumeJob(jobKey);
                    break;
                case "pause":
                    scheduler.pauseJob(jobKey);
                    break;
                case "trigger":
                    scheduler.triggerJob(jobKey);
                    break;
            }
        }
        return "redirect:/quartz/job/list";
    }

}
